package com.sparrow.source.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sparrow.source.common.dto.DeviceUserListRes;
import com.sparrow.source.common.dto.DeviceVerifyLog;
import com.sparrow.source.common.dto.Result;
import com.sparrow.source.common.dto.UnvDeviceInfo;
import com.sparrow.source.common.dto.UnvDeviceQueryRequest;
import com.sparrow.source.common.dto.UnvPerson;
import com.sparrow.source.common.dto.convert.UnvDeviceConvert;
import com.sparrow.source.common.enums.ResultEnum;
import com.sparrow.source.persistense.IasUser;
import com.sparrow.source.persistense.UnvDevice;
import com.sparrow.source.persistense.mapper.UnvDeviceMapper;
import com.sparrow.source.service.IIasUserService;
import com.sparrow.source.service.IUnvDeviceService;
import com.sparrow.source.service.IasDeviceUserService;
import com.sparrow.source.third.UnvClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author bryceyung
 * @since 2024/11/19
 */
@Service
@Slf4j
public class UnvDeviceServiceImpl extends ServiceImpl<UnvDeviceMapper, UnvDevice> implements IUnvDeviceService {

    @Autowired
    private UnvClient unvClient;

    @Autowired
    private UnvDeviceConvert unvDeviceConvert;

    @Autowired
    private IIasUserService iasUserService;

    @Autowired
    private IasDeviceUserService deviceUserService;

    @Autowired
    private Executor threadPoolTaskExecutor;

    @Override
    public Boolean addDevice(UnvDevice device) {
        device.setCreateTime(new Date());
        return baseMapper.insert(device) > 0 ? true : false;
    }

    /**
     * 设备信息同步
     *
     * @param deviceId
     * @return
     */
    @Override
    public UnvDevice sync(Integer deviceId) {
        UnvDeviceInfo unvDeviceInfo = unvClient.getDeviceInfo(deviceId);
        if (unvDeviceInfo == null) {
            return null;
        }
        UnvDevice device = unvDeviceConvert.convert2DataSource(unvDeviceInfo);
        device.setId(deviceId);
        device.setSyncTime(new Date());
        return baseMapper.updateById(device) > 0 ? device : null;
    }

    @Override
    public IPage<UnvDevice> queryDevicePage(UnvDeviceQueryRequest queryRequest, Page<UnvDevice> page) {
        return baseMapper.selectWithParam(queryRequest.getName(), queryRequest.getChannel(), queryRequest.getIp(),
                queryRequest.getSerialNum(), page);
    }

    @Override
    public Result addPersonInfo(Integer deviceId, List<Integer> uids) {
        //校验是否有人脸信息
        AtomicReference<Boolean> faceFlag = new AtomicReference<>(false);
        StringBuffer wrongUid = new StringBuffer();
        List<IasUser> userList = Lists.newArrayList();
        uids.forEach(data -> {
            IasUser iasUser = iasUserService.getByUid(data);
            userList.add(iasUser);
            if (iasUser == null || iasUser.getFaceImg() == null) {
                faceFlag.set(false);
                wrongUid.append(data).append(",");
            }
        });
        //        if (faceFlag.get()) {
        //            log.info("addPersonInfo，用户缺少人脸数据：{}", wrongUid.substring(0, wrongUid.length() - 1));
        //            return Result.build(ResultEnum.BAD_REQUEST).setMessage("用户信息不全，请检查人脸数据");
        //        }
        // 校验uid个数
        UnvPerson person = unvClient.addPersonInfo(deviceId, userList);
        return Result.build(ResultEnum.SUCCESS).setObject(person);
    }

    @Override
    public Result syncAllPersonInfo(Integer deviceId) {
        // 首先批量删除
        unvClient.truncatePeopleLibraries(deviceId);
        List<IasUser> allUser = iasUserService.lambdaQuery().eq(IasUser::getDeleted, false).list();
        //UNV接口要求单批量一次最多六个
        List<List<IasUser>> userChunk = chunkList(allUser, 6);
        AtomicReference<Integer> count = new AtomicReference<>(1);
        userChunk.forEach(data -> {
            log.info("[syncAllPersonInfo] chunk count:[{}],size:[{}]", count, data.size());
            count.getAndSet(count.get() + 1);
            threadPoolTaskExecutor.execute(() -> {
                unvClient.addPersonInfo(deviceId, data);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        });
        return Result.build(ResultEnum.SUCCESS);
    }

    @Override
    public UnvDevice getById(Integer deviceId) {
        UnvDevice device = baseMapper.selectById(deviceId);
        if (device == null) {
            return null;
        }
        List<DeviceVerifyLog> logList = baseMapper.selectDetailInfoByUserId(deviceId, 10);
        device.setReportLog(logList);
        device.setDeviceUserList(deviceUserService.queryDeviceUserList(deviceId));
        return device;
    }

    @Override
    public List<DeviceUserListRes> queryDeviceUserList(Integer deviceId) {
        return baseMapper.selectDeivceUserList(deviceId);
    }

    @Override
    public List<UnvDevice> queryOffLineDevices() {
        return baseMapper.selectOffLineDevices();
    }

    /**
     * 数据分组
     *
     * @param list
     * @param chunkSize
     * @param <T>
     * @return
     */
    public static <T> List<List<T>> chunkList(List<T> list, int chunkSize) {
        List<List<T>> chunks = new ArrayList<>();
        for (int i = 0; i < list.size(); i += chunkSize) {
            int toIndex = Math.min(i + chunkSize, list.size());
            chunks.add(list.subList(i, toIndex));
        }
        return chunks;
    }
}
